/*
 * MockReadableSelectableChannel.java    0.0.1    21/set/2009
 * 
 * Copyright (c) 2009 mentalsmash.org
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * The use of the Apache License does not indicate that this project is
 * affiliated with the Apache Software Foundation.
 */ 
package org.mentalsmash.tazio.net.cs.server.impl.mock;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.Pipe;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SelectableChannel;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implements a ReadableByteChannel. The data that this channel gives back upon <code>read()</code>
 * operations is the one that an user can provide calling
 * {@link MockReadableSelectableChannel#setDataToBeRead(byte[]) setDataToBeRead() }.
 * <p>
 * This channel can be registered to a selector for readiness events.
 * </p>
 * <p>
 * Used for testing purposes
 * </p>
 * @version    0.0.1    21/set/2009    
 * @author     Andrea Reale <andrea.reale@gmail.com>
 */
public class MockReadableSelectableChannel extends MockSelectableChannel 
	implements ReadableByteChannel {

	private final static Logger log = LoggerFactory.getLogger(MockReadableSelectableChannel.class);

	private final Pipe inPipe;


	/**
	 * Creates a new MockReadableSelectableChannel
	 * @throws IOException if some error occurs while setting up the channel
	 */
	public MockReadableSelectableChannel() throws IOException{

		inPipe = Pipe.open();
	}

	/**
	 * The end of the pipe that is being exposed to the public
	 * @return The end of the pipe that is being exposed to the public
	 */
	@Override
	protected SelectableChannel getChannel(){
		return inPipe.source();
	}

	
	/**
	 * Sets the data that subsequent <code>read()</code> calls to this channel will return.
	 * @param data the data that subsequent <code>read()</code> calls to this channel will return.
	 * @return the number of bytes from <code>data</code> that were actually set on the channel
	 */
	public int setDataToBeRead(byte[] data){
		ByteBuffer src;
		int written = 0;
		
		if(data == null){
			log.warn("Noting to be set in the mock channel");
			return written; 
		}
		
		if(data.length > CHANNEL_SIZE){
			String msg = "Maximum size of data has to be: " + CHANNEL_SIZE + " bytes";
			log.error(msg);
			throw new IllegalArgumentException(msg);
		}
		
		src = ByteBuffer.wrap(data);
		
		try {
			written = inPipe.sink().write(src);
		} catch (IOException e) {
			log.error("Unexpected exception",e);
			throw new RuntimeException("Unexpected exception",e);
		}
		
		return written;
		
		
	}



	/* (non-Javadoc)
	 * @see java.nio.channels.spi.AbstractInterruptibleChannel#implCloseChannel()
	 */
	@Override
	protected void implCloseChannel() throws IOException {
		inPipe.sink().close();
		inPipe.source().close();

	}

	/* (non-Javadoc)
	 * @see java.nio.channels.ReadableByteChannel#read(java.nio.ByteBuffer)
	 */
	@Override
	public int read(ByteBuffer dst) throws IOException {
		return inPipe.source().read(dst);
	}





}
